package projectx.util;

import java.io.UnsupportedEncodingException;
import java.text.Collator;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

public final class StringUtil {

	// --------------------------------------------------------------------------
	// S T A T I C M E M B E R S
	//
	// --------------------------------------------------------------------------
	private static final String CHARSET_NAME = "UTF-8";

	private static final Logger LOGGER = Logger.getLogger(StringUtil.class
			.getName());
	private static final String PATTERN_LONG = "###,###";

	private static final String PATTERN_DECIMAL = "###,##0.00";

	private static final String PATTERN_PERCENT_DECIMAL = "#####0.00";

	private static final char CHAR_A = 65;

	private static final char CHAR_Z = 90;

	private static final char CHAR_0 = 48;

	private static final char CHAR_9 = 57;

	// --------------------------------------------------------------------------
	// C O N S T R U C T O R S
	//
	// --------------------------------------------------------------------------
	private StringUtil() {
		super();
	}

	// --------------------------------------------------------------------------
	// S T A T I C M E T H O D S
	//
	// --------------------------------------------------------------------------

	public static String trim(String s) {

		if (s == null || s.length() == 0) {
			return "";
		}
		int orgLength = s.length();
		int endIndex = orgLength;
		int startIndex = 0;

		while ((startIndex < orgLength)
				&& isLowerOrEqualWhitespace(s.charAt(startIndex))) {
			startIndex++;
		}
		while ((startIndex < endIndex)
				&& isLowerOrEqualWhitespace(s.charAt(endIndex - 1))) {
			endIndex--;
		}

		return (startIndex > 0 || endIndex < orgLength) ? s.substring(
				startIndex, endIndex) : s;
	}

	public static String[] trim(String[] arrays) {

		if (null == arrays || arrays.length == 0) {
			return arrays;
		}
		for (int i = 0; i < arrays.length; i++) {
			String s = arrays[i];
			if (null == s || s.length() == 0) {
				s = "";
			}
			int orgLength = s.length();
			int endIndex = orgLength;
			int startIndex = 0;

			while ((startIndex < orgLength)
					&& isLowerOrEqualWhitespace(s.charAt(startIndex))) {
				startIndex++;
			}
			while ((startIndex < endIndex)
					&& isLowerOrEqualWhitespace(s.charAt(endIndex - 1))) {
				endIndex--;
			}
			s = (startIndex > 0 || endIndex < orgLength) ? s.substring(
					startIndex, endIndex) : s;
			arrays[i] = s;
		}
		return arrays;

	}

	public static String trimEnds(String s) {

		if (s == null || trim(s).length() == 0) {
			return "";
		}
		int orgLength = s.length();
		int endIndex = orgLength;

		while (isLowerOrEqualWhitespace(s.charAt(endIndex - 1))) {
			endIndex--;
		}

		return (endIndex < orgLength) ? s.substring(0, endIndex) : s;
	}

	private static boolean isLowerOrEqualWhitespace(char c) {

		return (c <= ' ' || Character.isWhitespace(c)) ? true : false;
	}

	public static String removeCRLF(String s) {

		if (s == null) {
			return "";
		}
		if (s.indexOf("\r") < 0 || s.indexOf("\n") < 0) {
			return s;
		}

		StringTokenizer st = new StringTokenizer(s);
		StringBuffer sb = new StringBuffer(s.length());

		while (st.hasMoreElements()) {

			sb.append(st.nextToken());
		}

		return sb.toString();
	}

	public static String int2str(int i, int len) {

		return int2str(i, len, false);
	}

	public static String int2str(int i, int len, boolean isZeroFill) {

		return str2fixedLen(String.valueOf(i), len, isZeroFill ? '0' : ' ',
				false, false);
	}

	public static String long2str(long l, int len) {

		return long2str(l, len, false);
	}

	public static String long2str(long l, int len, boolean isZeroFill) {

		return str2fixedLen(String.valueOf(l), len, isZeroFill ? '0' : ' ',
				false, false);
	}

	public static String numberFormat(double number) {

		return NumberFormat.getInstance().format(number);
	}

	public static String numberFormat(long number) {

		return NumberFormat.getInstance().format(number);
	}

	public static String numberFormat(double number, String pattern) {

		return getNumberFormat(pattern).format(number);
	}

	public static String numberFormat(long number, String pattern) {

		return getNumberFormat(pattern).format(number);
	}

	public static NumberFormat getNumberFormat(String pattern) {

		NumberFormat format = NumberFormat.getInstance();

		if (format instanceof DecimalFormat) {
			((DecimalFormat) format).applyPattern(pattern);
		}

		return format;
	}

	public static String str2fixedLen(String s, int len) {

		return str2fixedLen(s, len, ' ', true, true);
	}

	String str2fixedLen(String s, int len, char pad) {

		return str2fixedLen(s, len, pad, true, true);
	}

	public static String str2fixedLen(String s, int len, char pad,
			boolean leftJustify) {

		return str2fixedLen(s, len, pad, leftJustify, true);
	}

	public static String str2fixedLen(String s, int len, char pad,
			boolean leftJustify, boolean isTruncate) {

		String workStr = new String(getBytes(s));
		char[] workChar = workStr.toCharArray();

		// --- length in byte ---
		int byteLen = 0;

		// --- conversion loop ---
		for (int r = 0; r < workChar.length; r++) {

			// --- save the current character to handling buffer ---
			char c = workChar[r];

			// --- get the current char's byte length ---
			int thisLen = 2;
			if (((0x0020 <= c) && (c <= 0x007e)) || // ASCII half char
					((0xff61 <= c) && (c <= 0xff9f)) || // HANKAKU-KATAKANA
					(c == 0x00a5) || // YEN
					(c == 0x203e)) { // Tilde
				thisLen = 1;
			} else if ((0xd800 <= c) && (c <= 0xdbff)) { // Extended
				// Unicode
				// for Tiger
				r++;
			}

			// --- Truncate if the length is longer ---
			if (isTruncate && (byteLen + thisLen) > len) {
				if (byteLen < len) {
					workChar[r++] = ' ';
				}
				return new String(workChar, 0, r);
			}
			byteLen += thisLen;
		}

		if (byteLen >= len) {
			return workStr;
		}

		int fillerLen = (getBytes(new String(new char[] { pad })).length > 1) ? (len - byteLen) / 2
				: len - byteLen;
		char[] filler = new char[fillerLen];
		Arrays.fill(filler, pad);

		StringBuffer sb = new StringBuffer();
		if (leftJustify) {
			sb.append(workStr).append(filler);
		} else {
			sb.append(filler).append(workStr);
		}

		return sb.toString();
	}

	public static int length(String s) {

		return (s == null) ? 0 : getBytes(s).length;
	}

	public static String list2str(List list) {

		return list2str(list, ",");
	}

	public static String list2str(List list, String delim) {

		if (list == null) {
			return "";
		}

		Iterator iterator = list.iterator();
		StringBuffer sb = new StringBuffer();

		for (int i = 0; iterator.hasNext(); i++) {

			if (i > 0) {
				sb.append(delim);
			}
			sb.append(iterator.next());
		}

		return sb.toString();
	}

	public static String array2str(Object[] array) {

		return array2str(array, ",");
	}

	public static String array2str(Object[] array, String delim) {

		if (array == null) {
			return "";
		}

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < array.length; i++) {

			if (i > 0) {
				sb.append(delim);
			}
			sb.append(array[i]);
		}

		return sb.toString();
	}

	public static byte[] getBytes(String str) {

		try {

			return str.getBytes(CHARSET_NAME);
		} catch (UnsupportedEncodingException e) {

			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug(e);
			}
			return str.getBytes();
		}
	}

	public static String getBlankString(int len) {

		return getFilledString(' ', len);
	}

	public static String getFilledString(char pad, int len) {

		int tempLen = len;

		if (tempLen < 0) {
			tempLen = 0;
		}

		char[] filler = new char[tempLen];

		Arrays.fill(filler, pad);

		return new String(filler);
	}

	public static String replaceAll(String source, String regex,
			String replacement) {
		if (source == null || regex == null || replacement == null) {
			return null;
		}

		String tempSource = source;
		boolean isOK = tempSource.indexOf(regex) < 0;
		while (!isOK) {
			int pBegin = tempSource.indexOf(regex);
			String sBefore = tempSource.substring(0, pBegin);
			String sAfter = tempSource.substring(pBegin + regex.length());

			tempSource = sBefore + replacement + sAfter;

			isOK = tempSource.indexOf(regex) < 0;
		}
		return tempSource;
	}

	public static String trimString(String source) {
		if (source == null) {
			return null;
		}
		return source.trim();
	}

	public static boolean compareString(String s1, String s2) {
		if (s1 == null) {
			if (s2 == null) {
				return true;
			} else {
				return false;
			}
		} else {
			if (s2 == null) {
				return false;
			} else {
				Collator myCollator = Collator.getInstance();
				boolean b = (myCollator.compare(s1, s2) == 0); // FIXED
				return b;
			}
		}
	}

	public static int compareToString(String fromValue, String toValue) {
		String tempFromValue = fromValue;
		String tempToValue = toValue;

		if (tempFromValue != null && tempToValue == null) {
			return 1;
		} else if (tempToValue != null && tempFromValue == null) {
			return -1;
		} else if (tempFromValue == null && tempToValue == null) {
			return 0;
		}

		int fromLength = tempFromValue.length();
		int toLength = tempToValue.length();

		if (fromLength != 0 && toLength != 0) {
			if (fromLength != toLength) {
				if (fromLength > toLength) {
					tempToValue = StringUtil.str2fixedLen(tempToValue,
							fromLength, ' ', false);
				} else if (fromLength < toLength) {
					tempFromValue = StringUtil.str2fixedLen(tempFromValue,
							toLength, ' ', false);
				}
			}
			return tempFromValue.compareTo(tempToValue);
		}

		return tempFromValue.compareTo(tempToValue);
	}

	public static boolean isBlank(String s) {
		boolean isBlank = false;
		if ("".equals(trim(s))) {
			isBlank = true;
		}
		return isBlank;
	}

	public static char getNextChar(char c) {

		if (c == CHAR_Z) {
			return CHAR_0;
		} else if (c == CHAR_9) {
			return CHAR_A;
		} else {
			return (char) (c + 1);
		}
	}

	public static String formatDate(String s) {
		if (s == null)
			return null;
		String returnStr = "";
		if (s.indexOf("-") == -1) {
			if (s.length() == 8) {
				returnStr = s.substring(0, 4) + "-" + s.substring(4, 6) + "-"
						+ s.substring(6, 8);
			} else {
				returnStr = s;
			}

		} else {
			String[] array = s.split("-");
			for (int i = 0; i < array.length; i++) {
				returnStr = returnStr + array[i];
			}
		}

		return returnStr;
	}

	public static String toUpperCase(String source) {
		if (source != null) {
			return source.toUpperCase(Locale.getDefault());
		} else {
			return source;
		}
	}

	public static String[] toUpperCase(String[] arrays) {
		if (null == arrays || arrays.length == 0) {
			return arrays;
		}
		for (int i = 0; i < arrays.length; i++) {
			if (arrays[i] != null && arrays[i].length() > 0) {
				arrays[i] = arrays[i].toUpperCase();
			}
		}
		return arrays;
	}

	public static int stringToInt(String val) {
		int value = 0;
		try {
			value = NumberFormat.getIntegerInstance().parse(trim(val))
					.intValue();
		} catch (java.text.ParseException e1) {
			return value;
		}
		return value;
	}

	public static String subString(String val, int length, boolean isLeft) {

		String value = val;

		if (value == null || value.length() == 0) {
			return "";
		}

		if (isLeft) {
			if (val.length() > length) {
				value = val.substring(length);
			}
		} else {
			if (val.length() > length) {
				value = val.substring(0, val.length() - length);
			}

		}
		return value;

	}

	public static String subString(String val, int valLength, int subLength) {
		String value = "";
		if (val == null || val.length() == 0) {
			return value;
		}
		if (valLength == val.length()) {
			value = val.substring(valLength - subLength, valLength);
		}
		return value;
	}

	public static String formatLong(long num) {
		return numberFormat(num, PATTERN_LONG);
	}

	public static String formatLong(String num) {
		long lNum = 0;
		if (StringUtil.isBlank(num)) {
			return "";
		} else {
			lNum = Long.parseLong(num);
		}
		return numberFormat(lNum, PATTERN_LONG);
	}

	public static String formatDecimal(double num) {
		return numberFormat(num, PATTERN_DECIMAL);
	}

	public static String formatDecimal(String num) {
		double dNum = 0;
		if (!StringUtil.isBlank(num)) {
			dNum = Double.parseDouble(num);
		}
		return numberFormat(dNum, PATTERN_DECIMAL);
	}

	public static String fillString(String source, int len) {
		// FromLeft,�w�蕶��='0'
		return fillString(source, len, false);
	}

	public static String fillString(String source, int len,
			boolean fillStringFlag) {

		if (!fillStringFlag && isBlank(source)) {
			return null;
		}
		return fillString(source, '0', len, true);

	}

	public static String fillString(String source, char c, int len,
			boolean fromLeft) {
		String rslt = trim(source);

		int suffixLen = len - rslt.length();

		if (fromLeft) {
			return getFilledString(c, suffixLen) + rslt;
		} else {
			return rslt + getFilledString(c, suffixLen);
		}
	}

	public static boolean isNumeric(String str) {

		Pattern pattern = Pattern.compile("[0-9]*");

		Matcher isNum = pattern.matcher(str);

		if (!isNum.matches()) {
			return false;
		}

		return true;
	}

	public static String appendLike(String str) {

		StringBuffer strBf = new StringBuffer();
		if (isBlank(str)) {
			return "%";
		}

		strBf.append("%");
		strBf.append(str);
		strBf.append("%");

		return strBf.toString();
	}

	public static double getDouble(double d,int count) {
		java.math.BigDecimal   f1   =   new   java.math.BigDecimal(d);//小数点后保留2位，4舍5入
	    f1 = f1.setScale(count,java.math.BigDecimal.ROUND_HALF_UP);
	    return f1.doubleValue();
	}
}
